﻿package igz.fleaxy.ui.scrollbar
{
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.utils.Timer;
	import igz.fleaxy.Fleaxy;
	import igz.fleaxy.css.CssManager;
	import igz.fleaxy.ui.LinkUi;
	import igz.fleaxy.util.ObjectUtil;

	/**
	 * @author Intelygenz | www.intelygenz.com
	 */
	public class ScrollBarAbstract extends Sprite {
		
		protected var _ScrollContainer:ScrollContainerUi;
		protected var _Styles: Object;
		protected var _Settings: Object;

		protected var _Mark_OffsetX:Number;
		protected var _Mark_OffsetY:Number;

		protected var _Bg:Sprite;
		protected var _Mark:Sprite;
		
		protected var _TimerStartMove : Timer;
		protected var _TimerMove : Timer;
		protected var _MoveDirection : Boolean;
		
		public function set $BgColor ( p_color:uint ) : void {
			_Settings["bgColor"] = p_color;
			_Draw();
		}
		public function get $BgColor ( ) : uint {
			return _Settings["bgColor"];
		}
		
		public function set $BgAlpha ( p_alpha:Number ) : void {
			_Settings["bgAlpha"] = p_alpha;
			_Draw();
		}
		public function get $BgAlpha ( ) : Number {
			return _Settings["bgAlpha"];
		}
		
		public function set $MarkColor ( p_color:uint ) : void {
			_Settings["markColor"] = p_color;
			_Draw();
		}
		public function get $MarkColor ( ) : uint {
			return _Settings["markColor"];
		}
		
		public function set $MarkAlpha ( p_color:Number ) : void {
			_Settings["markAlpha"] = p_color;
			_Draw();
		}
		public function get $MarkAlpha ( ) : Number {
			return _Settings["markAlpha"];
		}

		/**
		 * Clase abstracta que aglutina la lógica necesaria para implementar ScrollBarV y ScrollBarH
		 *
		 * @param	p_scrollContainerUi
		 * @param	p_styles 	: { "backgroundStyle" : "scrollbarBg", "markStyle" : "scrollbarMark" }
		 * @param	p_settings
		 */
		public function ScrollBarAbstract( p_scrollContainerUi:ScrollContainerUi, p_styles:Object = null, p_settings:Object = null ) {

			_Settings = {
						// backgroundStyle
						  "bgSize" : 10
						, "bgColor"	: 0xCBCBCB
						, "bgRound"	: [0, 0, 0, 0]
						, "bgAlpha"	: 1
						, "bgFilters" : []
						, "bgBorder" : null //Color del borde
						, "bgBorderAlpha" : 1
						, "bgBorderThickness" : 0
						// markStyle
						, "markSize" : 10
						, "markColor" : 0x0000FF
						, "markRound" : [0, 0, 0, 0]
						, "markAlpha" : 1
						, "markFilters" : []
						, "markBorder" : null //Color del borde
						, "markBorderAlpha" : 1
						, "markBorderThickness" : 0
						// other settings
						, "size" : null // Tamaño de la barra de scroll
						, "cssName" : null
						, "alwaysVisible" : false
						, "showArrows" : false
						, "scrollSpeed" : 5
						, "autoPos" : true // Lo posiciona automáticamente a la derecha de su ScrollContainer
			};

			_Bg = new Sprite();
			addChild(_Bg);

			_Mark = new Sprite();
			_Mark.mouseEnabled  = true;
			_Mark.buttonMode    = true;
			_Mark.useHandCursor = true;
			_Mark.tabEnabled    = false;
			_Mark.addEventListener(MouseEvent.MOUSE_DOWN, _Mark_MouseDown);
			addChild( _Mark );
			_Styles = new Object();
			if ( p_styles != null ) {
				_SetSettingsByStyles( p_styles );
			}

			ObjectUtil.$Merge( p_settings, _Settings );
			$SetScrollContainerUi( p_scrollContainerUi );
			
			if ( _Settings["showArrows"] ) {
				_TimerStartMove = new Timer(500,1);
				_TimerStartMove.addEventListener(TimerEvent.TIMER, _TimerStartMove_OnTimer);
				
				_TimerMove = new Timer(50);
			}
		}
		
		private function _SetSettingsByStyles ( p_styles:Object ) : void {
			ObjectUtil.$Merge( p_styles, _Styles );
			
			var styles : Object;
			if ( _Styles["backgroundStyle"] != null ) {
				styles = { "bgSize"	  	: Number( _GetBgStyleValue( CssManager.$STYLE_SIZE ) )
						 , "bgColor"	: _GetBgStyleValue( CssManager.$STYLE_COLOR )
						 , "bgRound"	: _GetBgStyleValue( CssManager.$STYLE_ROUND )
						 , "bgAlpha"	: _GetBgStyleValue( CssManager.$STYLE_ALPHA )
						 , "bgFilters" 	: Fleaxy.$Current.$CssManager.$GetStyleFilters( _Styles["backgroundStyle"], _Settings["cssName"] )
						 , "bgBorder"	: _GetBgStyleValue( CssManager.$STYLE_BORDER )
						 , "bgBorderAlpha"	: _GetBgStyleValue( CssManager.$STYLE_BORDER_ALPHA )
						 , "bgBorderThickness" : Number( _GetBgStyleValue( CssManager.$STYLE_BORDER_THICKNESS ) )
				};
				ObjectUtil.$Merge( styles, _Settings, false );
			}

			if ( _Styles["markStyle"] != null ) {
				styles = { "markSize"  	: Number( _GetMarkStyleValue( CssManager.$STYLE_SIZE ) )
						, "markColor" 	: _GetMarkStyleValue( CssManager.$STYLE_COLOR )
						, "markRound" 	: _GetMarkStyleValue( CssManager.$STYLE_ROUND )
						, "markAlpha"	: _GetMarkStyleValue( CssManager.$STYLE_ALPHA )
						, "markFilters"	: Fleaxy.$Current.$CssManager.$GetStyleFilters( _Styles["markStyle"], _Settings["cssName"] )
						, "markBorder"	: _GetMarkStyleValue( CssManager.$STYLE_BORDER )
						, "markBorderAlpha"	: _GetMarkStyleValue( CssManager.$STYLE_BORDER_ALPHA )
						, "markBorderThickness" : Number( _GetMarkStyleValue( CssManager.$STYLE_BORDER_THICKNESS ) )
				};
				ObjectUtil.$Merge( styles, _Settings, false );
			}
			
			_Settings["bgRound"] = String(_Settings["bgRound"]).split(",");
			_Settings["markRound"] = String(_Settings["markRound"]).split(",");
			
			if ( _Settings["bgFilters"] != [] ) {
				_Bg.filters   = _Settings["bgFilters"];
			}
			if ( _Settings["markFilters"] != [] ) {
				_Mark.filters = _Settings["markFilters"];
			}
		}
		
		/**
		 * Cambia el aspecto de la barra de scroll en función de los estilos especificados
		 *
		 * @param	p_styles { "backgroundStyle" : "scrollbarBg", "markStyle" : "scrollbarMark" }
		 */
		public function $SetStyles ( p_styles:Object ) : void {
			_SetSettingsByStyles( p_styles );
			_Draw();
		}
		
		public function $SetMarkStyle ( p_markStyleName:String ) : void {
			_SetSettingsByStyles( { "markStyle": p_markStyleName } );
			_Draw();
		}
		
		public function $SetBgStyle ( p_backgroundStyleName:String ) : void {
			_SetSettingsByStyles( { "backgroundStyle": p_backgroundStyleName } );
			_Draw();
		}

		private function _GetBgStyleValue(p_styleParameter:String):String {
			return Fleaxy.$Current.$CssManager.$GetStyleValue(_Styles["backgroundStyle"], p_styleParameter, _Settings["cssName"]);
		}

		private function _GetMarkStyleValue(p_styleParameter:String):String {
			return Fleaxy.$Current.$CssManager.$GetStyleValue(_Styles["markStyle"], p_styleParameter, _Settings["cssName"]);
		}
		
		private function _Mark_MouseDown (p_mouseEvent: MouseEvent) : void {
			p_mouseEvent.stopPropagation();

			_Mark_OffsetX = p_mouseEvent.stageX - _Mark.x;
			_Mark_OffsetY = p_mouseEvent.stageY - _Mark.y;

			Fleaxy.$Current.$Stage.addEventListener(MouseEvent.MOUSE_UP, _Mark_MouseUp);
			Fleaxy.$Current.$Stage.addEventListener(MouseEvent.MOUSE_MOVE, _Mark_MouseMove);
		}
		private function _Mark_MouseUp (p_mouseEvent:MouseEvent) : void {
			Fleaxy.$Current.$Stage.removeEventListener(MouseEvent.MOUSE_UP, _Mark_MouseUp);
			Fleaxy.$Current.$Stage.removeEventListener(MouseEvent.MOUSE_MOVE, _Mark_MouseMove);
		}
		
		private function _ScrollContainer_Change ( p_event:Event ) : void {
			_Draw();
		}

		//
		// Functions to override
		//
		protected function _Draw() : void {
			
		}
		protected function _Mark_MouseMove ( p_mouseEvent:MouseEvent ) : void {
			
		}
		protected function _ScrollContainer_MouseWheel ( p_mouseEvent:MouseEvent ) : void {
			
		}

		/**
		 * Establece el contenedor scrollable que controlará
		 *
		 * @param	p_scrollContainer Contenedor
		 */
		public function $SetScrollContainerUi( p_scrollContainer:ScrollContainerUi ) : void {
		
			if ( _ScrollContainer != null ) {
			//	_ScrollContainer.removeEventListener(Event.CHANGE, _ScrollContainer_Change);
				_ScrollContainer.removeEventListener(MouseEvent.MOUSE_WHEEL, _ScrollContainer_MouseWheel);
				
				_ScrollContainer.parent.removeChild( this );
			}

			_ScrollContainer = p_scrollContainer;

			_ScrollContainer.addEventListener(Event.CHANGE, _ScrollContainer_Change);
			_ScrollContainer.addEventListener(MouseEvent.MOUSE_WHEEL, _ScrollContainer_MouseWheel);
			
			//if ( _ScrollContainer.parent != null ) {
				//_ScrollContainer.parent.addChild( this );
			//}
			//else {
				//throw new Error("ScrollBarAbstract $SetScrollContainerUi: Debe hacer addChild del scroll container");
			//}
		}
		
		public function $Refresh() : void {
			_Draw();
		}
		
		//
		// Botones de dirección
		//
		protected function _CreateArrowButtonBg () : Shape {
			var box : Shape = new Shape();
			box.graphics.beginFill( _Settings["markColor"], _Settings["markAlpha"] );
			if ( _Settings["markBorder"] != null && _Settings["markBorderThickness"] > 0 ) {
				box.graphics.lineStyle(_Settings["markBorderThickness"], _Settings["markBorder"], _Settings["markBorderAlpha"], true);
			}
			var size : Number = _Settings["bgSize"] - _Settings["markBorderThickness"];

			var margin : Number = _Settings["markBorderThickness"] / 2;
			box.graphics.drawRoundRectComplex( margin
											 , margin
											 , size
											 , size
											 , _Settings["markRound"][0], _Settings["markRound"][1]
											 , _Settings["markRound"][2], _Settings["markRound"][3]
											 );
			box.graphics.endFill();
			return box;
		}
		
		protected function _StopMove () : void {
			_TimerStartMove.stop();
			_TimerMove.stop();
		}
		
		private function _TimerStartMove_OnTimer( p_timerEvent:TimerEvent ):void {
			_TimerMove.start();
		}
	}

}